#ifndef NSI_SPIKE_UTIL_SIGNAL_H
#define NSI_SPIKE_UTIL_SIGNAL_H

#include "signal_base.h"
#include <signal.h>
#include "signal_chain.h"

namespace nsi {
namespace spike {

template <int Signal>
class signal
  : public signal_base
{
public:
  
  // Signal chain tyep
  typedef signal_chain<Signal> chain_type;

  // Signal value
  enum value_type
  {
    signal_value = Signal
  };

  // Default constructor
  explicit signal()
    : signal_base()
  {

  }

  // Copy constructor
  signal(const signal& other)
    : signal_base(other)
  {

  }

  // Destructor
  virtual ~signal()
  {

  }

  // Assignment operator
  signal& operator=(const signal& other)
  {
    return signal_base::operator=(other);
  }

  // Creates the signal handler
  bool create()
  {
    action_.sa_sigaction = signal::handler;
    return sigaction(value(), &action_, NULL) >= 0;
  }

  // Accessors
  int value() const
  {
    return signal_value;
  }

  static chain_type& chain()
  {
    return chain_type::instance();
  }

  // Add the handler function to the chain
  static void add(signal* sig)
  {
    chain().list_.push_front(sig);
  }

  template <typename SignalType>
  static void add(const SignalType& sig)
  {
    chain().list_.push_front(new SignalType(sig));
  }
 
  // Handler function wrapper for the signal
  static void handler(int signal, siginfo_t* info, void* ucontext)
  {
    typename chain_type::list_type::iterator iter = chain().list_.begin();
    for (;iter != chain().list_.end(); ++iter)
      if ((*iter)->operator()(info, ucontext))
        return;
  }

};

} // namespace spike
} // namespace nsi

#endif // !NSI_SPIKE_UTIL_SIGNAL_H
